/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "space_station.h"
#include "los_task.h"
#include "ohos_init.h"
#include "iot_errno.h"
#include "iot_pwm.h"
#include "iot_adc.h"
#include "iot_uart.h"
#include "picture.h"
#include "lcd.h"
#include "cmsis_os2.h"
#include "config_network.h"
#include "lwip/tcp.h"
#include "lwip/ip_addr.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include "lwip/inet_chksum.h"
#include "sht30.h"
#include "bh1750.h"
#include "mpu6050.h"
#include "mq2.h"
#include "s12d.h"
#include "sc8.h"
#include "mic.h"
#include "sc03.h"
#include "lcd_display.h"

extern const unsigned char gImage_isoftstone[IMAGE_MAXSIZE_ISOFTSTONE];
#define LOG_TAG "tcp"

#define SERVER_PORT 6666

#define BUFF_LEN 256

#define WIFI_SSID "SMART-R"
#define WIFI_PASSWORD "12345678"

float g_humi;
float g_temp;
double sht30_data[2] = {0};
double bh1750_data = 0.0;
short mpu6050_data[3] = {0};
float ppm;
float keyVoltage;
unsigned int adcdata = 0;
uint16_t carbon;
double oxygen;
uv_index_e uv_index;
int cclient_fd;
char send_buff[16];
uint8_t page, choose, ledflag, fanflag, heaterflag;
uint8_t uart1rxbuf[64], uart1txbuf[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};
/***************************************************************
 * 函数名称: task_one
 * 说    明: 线程函数1
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void task_one()
{
    lcd_display_init();
    int count = 0;

    IoTPwmInit(ELECTRICAL_MACHINERY_PORT);
    IoTPwmInit(LED_R_PORT);
    IoTPwmInit(LED_G_PORT);
    IoTPwmInit(LED_B_PORT);
    IoTPwmInit(BEEP_PORT);
    while (1)
    {
        switch (page)
        {
        case 0:
        {
            lcd_load_ui();
        }
        break;
        case 1:
        {
            lcd_show_string(96, 0, "CONTROL", LCD_RED, LCD_WHITE, 32, 0);
            lcd_show_string(0, 40, "LED", LCD_BLACK, LCD_WHITE, 32, 0);
            lcd_show_string(0, 72, "FAN", LCD_BLACK, LCD_WHITE, 32, 0);
            lcd_show_string(0, 112, "HEATER", LCD_BLACK, LCD_WHITE, 32, 0);
            lcd_fill(104, 40, 200, 72, LCD_WHITE);
            lcd_fill(104, 72, 200, 104, LCD_WHITE);
            lcd_fill(104, 104, 200, 136, LCD_WHITE);
            switch (choose)
            {
            case 0:
            {
                if (ledflag)
                    lcd_show_string(104, 40, "ON", LCD_RED, LCD_BLACK, 32, 0);
                else
                    lcd_show_string(104, 40, "OFF", LCD_RED, LCD_BLACK, 32, 0);
                if (fanflag)
                    lcd_show_string(104, 72, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 72, "OFF", LCD_RED, LCD_WHITE, 32, 0);
                if (heaterflag)
                    lcd_show_string(104, 104, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 112, "OFF", LCD_RED, LCD_WHITE, 32, 0);
            }
            break;
            case 1:
            {
                if (ledflag)
                    lcd_show_string(104, 40, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 40, "OFF", LCD_RED, LCD_WHITE, 32, 0);
                if (fanflag)
                    lcd_show_string(104, 72, "ON", LCD_RED, LCD_BLACK, 32, 0);
                else
                    lcd_show_string(104, 72, "OFF", LCD_RED, LCD_BLACK, 32, 0);
                if (heaterflag)
                    lcd_show_string(104, 104, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 112, "OFF", LCD_RED, LCD_WHITE, 32, 0);
            }
            break;
            case 2:
            {
                if (ledflag)
                    lcd_show_string(104, 40, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 40, "OFF", LCD_RED, LCD_WHITE, 32, 0);
                if (fanflag)
                    lcd_show_string(104, 72, "ON", LCD_RED, LCD_WHITE, 32, 0);
                else
                    lcd_show_string(104, 72, "OFF", LCD_RED, LCD_WHITE, 32, 0);
                if (heaterflag)
                    lcd_show_string(104, 104, "ON", LCD_RED, LCD_BLACK, 32, 0);
                else
                    lcd_show_string(104, 112, "OFF", LCD_RED, LCD_BLACK, 32, 0);
            }
            break;
            }
        }
        break;
        }
        LOS_Msleep(1000);
    }
}

void goWaring()
{
    for (int i = 0; i < 3; i++)
    {
        IoTPwmStart(LED_R_PORT, 99, 1000);
        IoTPwmStart(LED_G_PORT, 0, 1000);
        IoTPwmStart(LED_B_PORT, 0, 1000);
        IoTPwmStart(BEEP_PORT, 30, 1000);
        LOS_Msleep(1000);
        IoTPwmStop(LED_R_PORT);
        IoTPwmStop(LED_G_PORT);
        IoTPwmStop(LED_B_PORT);
        IoTPwmStop(BEEP_PORT);
    }
}
/***************************************************************
 * 函数名称: task_two
 * 说    明: 线程函数2
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void task_two()
{
    int count = 0;
    sc03_init();
    sht30_init();
    bh1750_init();
    mpu6050_init();
    /* 初始化mq2设备 */
    mq2_dev_init();

    LOS_Msleep(1000);

    /* 传感器校准 */
    mq2_ppm_calibration();

    IoTAdcInit(KEY_ADC_CHANNEL);
    mic_init();
    // sc8_init();
    s12d_init();
    while (1)
    {
        sht30_read_data(sht30_data);
        bh1750_read_data(&bh1750_data);
        mpu6050_read_data(mpu6050_data);
        // printf("x %d y %d z %d \r\n", mpu6050_data[0], mpu6050_data[1], mpu6050_data[2]);
        ppm = get_mq2_ppm();
        // carbon = sc8_get();
        carbon = 2099;
        uv_index = s12d_get_uv_index();
        oxygen = sc03_get() + 20.9;
        if (page == 0)
        {
            lcd_set_temperature(sht30_data[0]);
            lcd_set_humidity(sht30_data[1]);
            lcd_set_mq2(ppm);
            lcd_set_noise(mic_get_state());
            lcd_set_co2(carbon);
            lcd_set_uv_index(uv_index);
            lcd_set_o2(oxygen);
            lcd_set_ip(0x0102A8C0);
            lcd_set_port(6666);
            lcd_set_gravity(0);
            lcd_set_battery(55.5);
            lcd_set_fire(0);
        }
        if (cclient_fd)
        {
            memset(send_buff, 0, 16);
            sprintf(send_buff, "t%.2f", sht30_data[0]);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "h%.2f", sht30_data[1]);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "m%.2f", ppm);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "n%.2f", mic_get_state());
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "c%.2f", carbon);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "u%d", uv_index);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "o%.2f", oxygen);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "g%d", 0);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "b%.2f", 55.5);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
            LOS_Msleep(100);
            memset(send_buff, 0, 16);
            sprintf(send_buff, "f%d", 0);
            send(cclient_fd, send_buff, strlen(send_buff), 0);
        }
        LOS_Msleep(1000);
    }
}
void keyTask()
{
    while (1)
    {
        IoTAdcGetVal(KEY_ADC_CHANNEL, &adcdata);
        keyVoltage = (float)(adcdata * 3.3 / 1024.0);
        if (keyVoltage > 3.2)
        {
            // printf("no key\n");
        }
        else if (keyVoltage > 1.50)
        {
            printf("LEFT\n");
            page ^= 1;
            lcd_fill(0, 0, 320, 240, LCD_WHITE);
            choose = 0;
        }
        else if (keyVoltage > 1.0)
        {
            printf("DOWN\n");
            if (choose == 2)
                choose = 0;
            else
                choose++;
        }
        else if (keyVoltage > 0.5)
        {
            printf("RIGHT\n");
            if (page == 1)
            {
                switch (choose)
                {
                case 0:
                {
                    if (ledflag == 0)
                    {
                        ledflag = 1;
                        IoTPwmStart(LED_R_PORT, 99, 1000);
                        IoTPwmStart(LED_G_PORT, 0, 1000);
                        IoTPwmStart(LED_B_PORT, 0, 1000);
                        lcd_fill(104, 40, 200, 72, LCD_WHITE);
                        lcd_show_string(104, 40, "ON", LCD_RED, LCD_BLACK, 32, 0);
                    }
                    else
                    {
                        ledflag = 0;
                        IoTPwmStop(LED_R_PORT);
                        IoTPwmStop(LED_G_PORT);
                        IoTPwmStop(LED_B_PORT);
                        lcd_fill(104, 40, 200, 72, LCD_WHITE);
                        lcd_show_string(104, 40, "OFF", LCD_RED, LCD_BLACK, 32, 0);
                    }
                }
                break;
                case 1:
                {
                    if (fanflag == 0)
                    {
                        fanflag = 1;
                        IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 30, 1000);
                        lcd_fill(104, 72, 200, 104, LCD_WHITE);
                        lcd_show_string(104, 72, "ON", LCD_RED, LCD_BLACK, 32, 0);
                    }
                    else
                    {
                        fanflag = 0;
                        IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
                        lcd_fill(104, 72, 200, 104, LCD_WHITE);
                        lcd_show_string(104, 72, "OFF", LCD_RED, LCD_BLACK, 32, 0);
                    }
                }
                break;
                case 2:
                {
                    if (heaterflag == 0)
                    {
                        heaterflag = 1;
                        IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 10, 1000);
                        lcd_fill(104, 104, 200, 136, LCD_WHITE);
                        lcd_show_string(104, 104, "ON", LCD_RED, LCD_BLACK, 32, 0);
                    }
                    else
                    {
                        heaterflag = 0;
                        IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
                        lcd_fill(104, 104, 200, 136, LCD_WHITE);
                        lcd_show_string(104, 104, "OFF", LCD_RED, LCD_BLACK, 32, 0);
                    }
                }
                break;
                }
            }
        }
        else
        {
            printf("UP\n");
            if (choose == 0)
                choose = 2;
            else
                choose--;
        }
        LOS_Msleep(300);
    }
}
void tcp_server_msg_handle(int fd)
{
    char buf[BUFF_LEN]; // 接收缓冲区
    socklen_t client_addr_len;
    int cnt = 0, count;
    int client_fd;
    struct sockaddr_in client_addr = {0};

    printf("waitting for client connect...\n");
    /* 监听socket 此处会阻塞 */
    client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len);
    // client_fd = lwip_accept(fd, (struct sockaddr*)&client_addr, &client_addr_len);
    printf("[tcp server] accept <%s:%d>\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    cclient_fd = client_fd;
    printf("client_id:%d\n", client_fd);
    while (1)
    {
        count = recv(client_fd, buf, BUFF_LEN, 0); // read是阻塞函数，没有数据就一直阻塞
        // count = lwip_read(client_fd, buf, BUFF_LEN);  //read是阻塞函数，没有数据就一直阻塞
        if (count == -1)
        {
            printf("[tcp server] recieve data fail!\n");
            LOS_Msleep(3000);
            break;
        }
        printf("[tcp server] rev client msg:%s\n", buf);
        if (strstr(buf, "won"))
        {
            goWaring();
        }
        else if (strstr(buf, "lon"))
        {
            ledflag = 1;
            IoTPwmStart(LED_R_PORT, 99, 1000);
            IoTPwmStart(LED_G_PORT, 0, 1000);
            IoTPwmStart(LED_B_PORT, 0, 1000);
        }
        else if (strstr(buf, "loff"))
        {
            ledflag = 0;
            IoTPwmStop(LED_R_PORT);
            IoTPwmStop(LED_G_PORT);
            IoTPwmStop(LED_B_PORT);
        }
        else if (strstr(buf, "fon"))
        {
            fanflag = 1;
            IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 40, 1000);
        }
        else if (strstr(buf, "foff"))
        {
            fanflag = 0;
            IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
        }
        else if (strstr(buf, "hon"))
        {
            heaterflag = 1;
            IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 40, 1000);
        }
        else if (strstr(buf, "hoff"))
        {
            heaterflag = 0;
            IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
        }
        memset(buf, 0, BUFF_LEN);
        // sprintf(buf, "I have recieved %d bytes data! recieved cnt:%d", count, ++cnt);
        // printf("[tcp server] send msg:%s\n", buf);
        // send(client_fd, buf, strlen(buf), 0); // 发送信息给client
        // lwip_write(client_fd, buf, strlen(buf));  //发送信息给client
    }
    lwip_close(client_fd);
    lwip_close(fd);
}

int wifi_server(void *arg)
{
    int server_fd, ret;

    while (1)
    {
        server_fd = socket(AF_INET, SOCK_STREAM, 0); // AF_INET:IPV4;SOCK_STREAM:TCP
        // server_fd = lwip_socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
        if (server_fd < 0)
        {
            printf("create socket fail!\n");
            return -1;
        }

        /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket，而经历TIME_WAIT的过程。*/
        int flag = 1;
        ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
        if (ret != 0)
        {
            printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
        }

        struct sockaddr_in serv_addr = {0};
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP地址，需要进行网络序转换，INADDR_ANY：本地地址
        // serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
        serv_addr.sin_port = htons(SERVER_PORT); // 端口号，需要网络序转换
        /* 绑定服务器地址结构 */
        ret = bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
        // ret = lwip_bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        if (ret < 0)
        {
            printf("socket bind fail!\n");
            lwip_close(server_fd);
            return -1;
        }
        /* 监听socket 此处不阻塞 */
        ret = listen(server_fd, 64);
        // ret = lwip_listen(server_fd, 64);
        if (ret != 0)
        {
            printf("socket listen fail!\n");
            lwip_close(server_fd);
            return -1;
        }
        printf("[tcp server] listen:%d<%s:%d>\n", server_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
        tcp_server_msg_handle(server_fd); // 处理接收到的数据
        LOS_Msleep(1000);
    }
}

void wifi_process(void *args)
{
    unsigned int threadID_client, threadID_server;
    unsigned int ret = LOS_OK;

    WifiLinkedInfo info;

    uint8_t wifi_mode[] = "AP";
    uint8_t mac_address[] = {0x00, 0xdc, 0xb6, 0x90, 0x11, 0x00};

    FlashInit();
    VendorSet(VENDOR_ID_WIFI_MODE, wifi_mode, sizeof(wifi_mode)); // 配置为Wifi AP模式
    VendorSet(VENDOR_ID_MAC, mac_address, sizeof(mac_address));
    VendorSet(VENDOR_ID_WIFI_SSID, WIFI_SSID, sizeof(WIFI_SSID));
    VendorSet(VENDOR_ID_WIFI_PASSWD, WIFI_PASSWORD,
              sizeof(WIFI_PASSWORD));

    SetApModeOff();
    SetApModeOn();

    CreateThread(&threadID_server, wifi_server, NULL, "server@ process");
}
void su03tTask()
{
    unsigned int ret;
    IotUartAttribute attr;
    // 串口注销
    IoTUartDeinit(EUART2_M1);
    // 串口配置
    attr.baudRate = 9600;
    attr.dataBits = IOT_UART_DATA_BIT_8;
    attr.pad = IOT_FLOW_CTRL_NONE;
    attr.parity = IOT_UART_PARITY_NONE;
    attr.rxBlock = IOT_UART_BLOCK_STATE_NONE_BLOCK;
    attr.stopBits = IOT_UART_STOP_BIT_1;
    attr.txBlock = IOT_UART_BLOCK_STATE_NONE_BLOCK;

    IoTUartInit(EUART2_M1, &attr);

    while (1)
    {
        ret = IoTUartRead(EUART2_M1, uart1rxbuf, 64);
        if (ret > 0)
        {
            if (uart1rxbuf[0] == 0x11)
            {
                ledflag = 1;
                IoTPwmStart(LED_R_PORT, 99, 1000);
                IoTPwmStart(LED_G_PORT, 0, 1000);
                IoTPwmStart(LED_B_PORT, 0, 1000);
            }
            else if (uart1rxbuf[0] == 0x22)
            {
                ledflag = 0;
                IoTPwmStop(LED_R_PORT);
                IoTPwmStop(LED_G_PORT);
                IoTPwmStop(LED_B_PORT);
            }
            else if (uart1rxbuf[0] == 0x33)
            {
                fanflag = 1;
                IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 40, 1000);
            }
            else if (uart1rxbuf[0] == 0x44)
            {
                fanflag = 0;
                IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
            }
            else if (uart1rxbuf[0] == 0x55)
            {
                heaterflag = 1;
                IoTPwmStart(ELECTRICAL_MACHINERY_PORT, 40, 1000);
            }
            else if (uart1rxbuf[0] == 0x66)
            {
                heaterflag = 0;
                IoTPwmStop(ELECTRICAL_MACHINERY_PORT);
            }
            else if (uart1rxbuf[0] == 0x77)
            {
                // printf("7777");
            }
            else if (uart1rxbuf[0] == 0x88)
            {
                uart1txbuf[2] = 0x02;
                uart1txbuf[3] = (char)sht30_data[0];
                IoTUartWrite(EUART2_M1, uart1txbuf, 6);
            }
            else if (uart1rxbuf[0] == 0x99)
            {
                uart1txbuf[2] = 0x03;
                uart1txbuf[3] = (char)sht30_data[1];
                IoTUartWrite(EUART2_M1, uart1txbuf, 6);
            }
        }
        LOS_Msleep(10);
    }
}
/***************************************************************
 * 函数名称: task_example
 * 说    明: 内核任务例程
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void task_example()
{
    unsigned int thread_id1;
    unsigned int thread_id2;
    unsigned int thread_id3;
    unsigned int thread_id4;
    unsigned int thread_id5;

    TSK_INIT_PARAM_S task1 = {0};
    TSK_INIT_PARAM_S task2 = {0};
    TSK_INIT_PARAM_S task3 = {0};
    TSK_INIT_PARAM_S task4 = {0};
    TSK_INIT_PARAM_S task5 = {0};

    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)task_one;
    task1.uwStackSize = 2048;
    task1.pcName = "Task_One";
    task1.usTaskPrio = 25;
    LOS_TaskCreate(&thread_id1, &task1);

    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)task_two;
    task2.uwStackSize = 2048;
    task2.pcName = "Task_Two";
    task2.usTaskPrio = 23;
    LOS_TaskCreate(&thread_id2, &task2);

    task3.pfnTaskEntry = (TSK_ENTRY_FUNC)wifi_process;
    task3.uwStackSize = 2048;
    task3.pcName = "wifi_process";
    task3.usTaskPrio = 24;
    LOS_TaskCreate(&thread_id3, &task3);

    task4.pfnTaskEntry = (TSK_ENTRY_FUNC)keyTask;
    task4.uwStackSize = 2048;
    task4.pcName = "keyTask";
    task4.usTaskPrio = 25;
    LOS_TaskCreate(&thread_id4, &task4);

    task5.pfnTaskEntry = (TSK_ENTRY_FUNC)su03tTask;
    task5.uwStackSize = 2048;
    task5.pcName = "su03tTask";
    task5.usTaskPrio = 25;
    LOS_TaskCreate(&thread_id5, &task5);
}

APP_FEATURE_INIT(task_example);
